using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using SeataNet.Core;
using SeataNet.Core.AT;
using SeataNet.Core.Configuration;
using SeataNet.Core.Context;
using SeataNet.Core.Monitor;
using SeataNet.Core.TCC;
using SeataNet.Core.Transaction;

namespace SeataNet.PerformanceTests
{
    /// <summary>
    /// 性能测试基类
    /// </summary>
    public abstract class PerformanceTestBase
    {
        protected readonly IServiceProvider _serviceProvider;
        protected readonly ILogger _logger;
        protected readonly ITransactionManager _transactionManager;
        protected readonly ITransactionMonitor _monitor;

        protected PerformanceTestBase()
        {
            var services = new ServiceCollection();
            ConfigureServices(services);
            _serviceProvider = services.BuildServiceProvider();
            _logger = _serviceProvider.GetRequiredService<ILogger<PerformanceTestBase>>();
            _transactionManager = _serviceProvider.GetRequiredService<ITransactionManager>();
            _monitor = _serviceProvider.GetRequiredService<ITransactionMonitor>();
        }

        protected virtual void ConfigureServices(IServiceCollection services)
        {
            services.AddLogging(builder => builder.AddConsole().SetMinimumLevel(LogLevel.Warning));
            services.AddSeataNet(config =>
            {
                config.ApplicationId = "performance-test";
                config.TxServiceGroup = "default";
                config.EnableAutoDataSourceProxy = true;
                config.EnablePerformanceMonitor = true;
            });
            services.AddAtMode();
            services.AddTccMode();
        }

        /// <summary>
        /// 执行性能测试
        /// </summary>
        /// <param name="testName">测试名称</param>
        /// <param name="concurrency">并发数</param>
        /// <param name="iterations">每个并发执行的迭代次数</param>
        /// <param name="testAction">测试操作</param>
        /// <returns>测试结果</returns>
        protected async Task<PerformanceTestResult> RunPerformanceTestAsync(
            string testName,
            int concurrency,
            int iterations,
            Func<Task> testAction)
        {
            // 预热
            await WarmUpAsync(testAction);

            var stopwatch = new Stopwatch();
            var tasks = new List<Task>();
            var exceptions = new List<Exception>();

            // 重置监控指标
            _monitor.ResetMetrics();

            _logger.LogInformation($"开始性能测试: {testName}, 并发数: {concurrency}, 迭代次数: {iterations}");

            stopwatch.Start();

            // 创建并发任务
            for (int i = 0; i < concurrency; i++)
            {
                tasks.Add(Task.Run(async () =>
                {
                    for (int j = 0; j < iterations; j++)
                    {
                        try
                        {
                            await testAction();
                        }
                        catch (Exception ex)
                        {
                            lock (exceptions)
                            {
                                exceptions.Add(ex);
                            }
                        }
                    }
                }));
            }

            // 等待所有任务完成
            await Task.WhenAll(tasks);

            stopwatch.Stop();

            // 获取监控指标
            var metrics = _monitor.GetMetrics();

            var result = new PerformanceTestResult
            {
                TestName = testName,
                Concurrency = concurrency,
                Iterations = iterations,
                TotalIterations = concurrency * iterations,
                ElapsedMilliseconds = stopwatch.ElapsedMilliseconds,
                ThroughputPerSecond = (double)(concurrency * iterations) / stopwatch.Elapsed.TotalSeconds,
                SuccessCount = metrics.TotalCount - exceptions.Count,
                FailureCount = exceptions.Count,
                AverageTransactionDuration = metrics.AverageDuration,
                MaxTransactionDuration = metrics.MaxDuration,
                MinTransactionDuration = metrics.MinDuration,
                Exceptions = exceptions
            };

            _logger.LogInformation($"性能测试完成: {testName}, 吞吐量: {result.ThroughputPerSecond:F2} TPS, 成功率: {(double)result.SuccessCount / result.TotalIterations * 100:F2}%");

            return result;
        }

        /// <summary>
        /// 预热
        /// </summary>
        /// <param name="testAction">测试操作</param>
        private async Task WarmUpAsync(Func<Task> testAction)
        {
            _logger.LogInformation("开始预热...");
            for (int i = 0; i < 10; i++)
            {
                try
                {
                    await testAction();
                }
                catch
                {
                    // 忽略预热阶段的异常
                }
            }
            _logger.LogInformation("预热完成");
        }

        /// <summary>
        /// 生成测试报告
        /// </summary>
        /// <param name="results">测试结果集合</param>
        /// <returns>测试报告</returns>
        protected string GenerateReport(List<PerformanceTestResult> results)
        {
            var report = new System.Text.StringBuilder();
            report.AppendLine("=====================================");
            report.AppendLine("         SeataNet 性能测试报告");
            report.AppendLine("=====================================");
            report.AppendLine();

            foreach (var result in results)
            {
                report.AppendLine($"测试名称: {result.TestName}");
                report.AppendLine($"并发数: {result.Concurrency}");
                report.AppendLine($"每个并发迭代次数: {result.Iterations}");
                report.AppendLine($"总迭代次数: {result.TotalIterations}");
                report.AppendLine($"总耗时: {result.ElapsedMilliseconds} ms");
                report.AppendLine($"吞吐量: {result.ThroughputPerSecond:F2} TPS");
                report.AppendLine($"成功次数: {result.SuccessCount}");
                report.AppendLine($"失败次数: {result.FailureCount}");
                report.AppendLine($"成功率: {(double)result.SuccessCount / result.TotalIterations * 100:F2}%");
                report.AppendLine($"平均事务持续时间: {result.AverageTransactionDuration} ms");
                report.AppendLine($"最大事务持续时间: {result.MaxTransactionDuration} ms");
                report.AppendLine($"最小事务持续时间: {result.MinTransactionDuration} ms");

                if (result.Exceptions.Any())
                {
                    report.AppendLine("异常信息:");
                    foreach (var ex in result.Exceptions.Take(5)) // 只显示前5个异常
                    {
                        report.AppendLine($"  - {ex.GetType().Name}: {ex.Message}");
                    }
                    if (result.Exceptions.Count > 5)
                    {
                        report.AppendLine($"  ... 还有 {result.Exceptions.Count - 5} 个异常");
                    }
                }

                report.AppendLine();
                report.AppendLine("-------------------------------------");
                report.AppendLine();
            }

            return report.ToString();
        }
    }

    /// <summary>
    /// 性能测试结果
    /// </summary>
    public class PerformanceTestResult
    {
        public string TestName { get; set; }
        public int Concurrency { get; set; }
        public int Iterations { get; set; }
        public int TotalIterations { get; set; }
        public long ElapsedMilliseconds { get; set; }
        public double ThroughputPerSecond { get; set; }
        public int SuccessCount { get; set; }
        public int FailureCount { get; set; }
        public long AverageTransactionDuration { get; set; }
        public long MaxTransactionDuration { get; set; }
        public long MinTransactionDuration { get; set; }
        public List<Exception> Exceptions { get; set; } = new List<Exception>();

        // Additional computed properties
        public int TotalRequests => TotalIterations;
        public int SuccessfulRequests => SuccessCount;
        public int FailedRequests => FailureCount;
        public long TotalTime => ElapsedMilliseconds;
        public double Throughput => ThroughputPerSecond;
        public double SuccessRate => TotalIterations > 0 ? (double)SuccessCount / TotalIterations * 100 : 0;
        public long AverageResponseTime => AverageTransactionDuration;
        public long MinResponseTime => MinTransactionDuration;
        public long MaxResponseTime => MaxTransactionDuration;
        public long P50ResponseTime => AverageTransactionDuration; // Simplified
        public long P95ResponseTime => (long)(MaxTransactionDuration * 0.95); // Simplified
        public long P99ResponseTime => (long)(MaxTransactionDuration * 0.99); // Simplified
    }
}